package org.osomit.sacct.session.token.impl;

import org.osomit.sacct.session.token.iface.TokenState;
import org.osomit.sacct.session.token.iface.Token;
import org.osomit.sacct.session.token.iface.TokenExpirationPolicy;
import org.osomit.sacct.security.otp.iface.OTPToken;

import javax.crypto.SecretKey;

/**
 * @author Jian Fang (John.Jian.Fang@gmail.com)
 *
 * Date: Jul 1, 2009
 */
public final class SessionToken implements Token, TokenState {
    private static final long serialVersionUID = -1902917625235927536L;
    
    public static String PREFIX = "SACCT";

    private final TokenExpirationPolicy expirationPolicy;

    private final String id;

    private long lastTimeUsed;

    private long countUsed;

    private long creationTime;

    private SecretKey sessionKey;
    
    // Flag to enforce manual expiration.
    private boolean expired = false;

    private OTPToken otpToken;

    public SessionToken(final String id, final TokenExpirationPolicy expirationPolicy) {
        this.expirationPolicy = expirationPolicy;
        this.id = id;
        this.creationTime = System.currentTimeMillis();
        this.lastTimeUsed = this.creationTime;
        this.countUsed = 0;
    }

    public OTPToken getOtpToken() {
        return otpToken;
    }

    public void setOtpToken(OTPToken otpToken) {
        this.otpToken = otpToken;
    }

    public SecretKey getSessionKey() {
        this.updateState();
        return this.sessionKey;
    }

    public void setSessionKey(SecretKey sessionKey) {
        this.sessionKey = sessionKey;
    }

    private void updateState() {
        this.lastTimeUsed = System.currentTimeMillis();
        this.countUsed++;
    }

    public long getCreationTime() {
        return creationTime;
    }

    public long getLastTimeUsed() {
        return lastTimeUsed;
    }

    public final String getId() {
        return this.id;
    }

    public long getCountUsed() {
        return this.countUsed;
    }

    public boolean isExpired() {
        return this.expirationPolicy.isExpired(this) || isExpiredInternal();
    }
    
    protected boolean isExpiredInternal() {

        return this.expired;
    }

    public void expire() {
        this.expired = true;
    }

    public String generateOTP() {

        if(otpToken != null)
            return otpToken.generateOTP();

        return null;
    }
}
